package com.jic.veteran.portal.service.impl;

import static java.util.Collections.emptyList;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageHelper;
import com.jic.veteran.common.pay.SybUtil;
import com.jic.veteran.common.util.IdWorker;
import com.jic.veteran.mapper.ProjectDonationDetailMapper;
import com.jic.veteran.mapper.UmsMemberMapper;
import com.jic.veteran.model.PayInfo;
import com.jic.veteran.model.ProjectDonationDetail;
import com.jic.veteran.model.ProjectDonationDetailExample;
import com.jic.veteran.model.UmsMember;
import com.jic.veteran.portal.dao.DonatePayDetailDao;
import com.jic.veteran.portal.dao.ProjectDonationDetailDao;
import com.jic.veteran.portal.domain.DonatePayDetail;
import com.jic.veteran.portal.domain.DonationListDto;
import com.jic.veteran.portal.domain.ProjectDonationTotalDto;
//import com.jic.veteran.portal.service.DonatePayService;
import com.jic.veteran.portal.service.ProjectDonationService;
import com.jic.veteran.portal.service.ProjectService;
import com.jic.veteran.portal.service.UmsMemberCacheService;
import com.jic.veteran.portal.service.UmsMemberService;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
public class ProjectDonationServiceImpl implements ProjectDonationService {
    @Autowired
    private UmsMemberMapper umsMemberMapper;
    @Autowired
    private DonatePayDetailDao donatePayDetailDao;
    @Autowired
    private ProjectDonationDetailMapper projectDonationDetailMapper;
    @Autowired
    private UmsMemberCacheService umsMemberCacheService;
    @Autowired
    private UmsMemberService umsMemberService;
    @Autowired
    private ProjectService projectService;
    @Autowired
    private IdWorker idWorker;
//    @Autowired
//    private DonatePayService donatePayService;
    @Autowired
    private ProjectDonationDetailDao projectDonationDetailDao;

    @Value("${wx.wxAppId}")
    private String wxAppId;
    @Value("${wx.payNotifyUrl}")
    private String payNotifyUrl;

    @Override
    public List<ProjectDonationDetail> list(String openId, Integer pageSize, Integer pageNum) {
        List<ProjectDonationDetail> projectDonationDetailList = umsMemberCacheService.getPersonDonationList(openId);
        if(CollectionUtil.isEmpty(projectDonationDetailList)) {
            PageHelper.startPage(pageNum,pageSize);
            ProjectDonationDetailExample projectDonationDetailExample = new ProjectDonationDetailExample();
            if(StrUtil.isNotEmpty(openId)) {
                projectDonationDetailExample.createCriteria().andUserIdEqualTo(openId);
            }
            projectDonationDetailExample.setOrderByClause("donation_time desc");
            projectDonationDetailList = projectDonationDetailMapper.selectByExample(projectDonationDetailExample);
            if(CollectionUtil.isNotEmpty(projectDonationDetailList)) {
                umsMemberCacheService.setPersonDonationAllList(openId,projectDonationDetailList);
            }
        }
        return projectDonationDetailList;
    }

    @Override
    public ProjectDonationDetail getItem(Long id) {
        return null;
    }

    @Override
    @Transactional
    public String pay(double trxamt,String openid,String projectId) {
        UmsMember umsMember = umsMemberService.getByUsername(openid);
        if(null != umsMember) {
            String reqsn = String.valueOf(idWorker.nextId());
            BigDecimal payAmt = NumberUtil.mul(trxamt * 100);
            Map<String, String> payResult = null;
            try {
//                payResult = SybPayUtil.pay(payAmt.longValue(), reqsn, openid, payNotifyUrl, wxAppId, umsMember.getIdno(), umsMember.getCname());
//                payResult = donatePayService.pay(payAmt.longValue(),reqsn,openid, payNotifyUrl, wxAppId);
            } catch (Exception e) {
                log.info("通联支付第一步失败:{}",e.getMessage());
            }
            if(null != payResult) {
                String retcode = payResult.get("retcode");
                String trxstatus = payResult.get("trxstatus");
                if(StrUtil.isNotEmpty(retcode) && StrUtil.isNotEmpty(trxstatus)) {
                    JSONObject jsonObject = JSONUtil.parseObj(payResult);
                    DonatePayDetail donatePayDetail = JSONUtil.toBean(jsonObject, DonatePayDetail.class);
                    if(donatePayDetail != null) {
                        donatePayDetail.setTrxamt(NumberUtil.toBigDecimal(trxamt));
                        donatePayDetail.setProjectId(projectId);
                        donatePayDetail.setReqsn(reqsn);
                        donatePayDetail.setRetcode(retcode);
                        donatePayDetail.setTrxstatus(trxstatus);
                        donatePayDetail.setOpenid(openid);
                        JSONObject projectBasic = projectService.getProjectBasic(projectId);
                        if (null != projectBasic && projectBasic.containsKey("projectName")) {
                            donatePayDetail.setProjectName(projectBasic.getStr("projectName"));
                        }
                        donatePayDetail.setTrxdate(DateUtil.format(DateUtil.date(),"yyyy-MM-dd"));
                        if("SUCCESS".equals(retcode) && "0000".equals(trxstatus)) {
                            donatePayDetail.setPayStatus("0");
                        } else if("FAIL".equals(retcode)) {
                            donatePayDetail.setPayStatus("2");
                        } else {
                            donatePayDetail.setPayStatus("2");
                        }
                        donatePayDetailDao.insert(donatePayDetail);
                        return donatePayDetail.getPayinfo();
                    }
                }
            }
        }
        return null;
    }

    @Override
    @Transactional
    public String payCallback(TreeMap<String, String> notifyData){
        PayInfo payInfo = umsMemberCacheService.getPayInfo();
        String appkey = "";
        if("RSA".equals(notifyData.get("signtype")))
            appkey = payInfo.getRsaPublicKey();
        else if("SM2".equals(notifyData.get("signtype")))
            appkey = payInfo.getSm2PublicKey();
        else
            appkey = payInfo.getMd5Key();
        boolean isSign = false;// 接受到推送通知,首先验签
        try {
            isSign = SybUtil.validSign(notifyData, appkey, notifyData.get("signtype"));
        } catch (Exception e) {
            log.info("支付回调失败:{}",e.getMessage());
            return "fail";
        }
        log.info("验签结果:{}",isSign);
        if(isSign) {
            String trxstatus = notifyData.get("trxstatus");
            if("0000".equals(trxstatus)) {
                String trxid = notifyData.get("trxid");
                if (StrUtil.isNotEmpty(trxid)) {
                    List<DonatePayDetail> donatePayDetails = donatePayDetailDao.getItemByTrxidByStatus(trxid,"0");
                    if(!donatePayDetails.isEmpty()) {
                        List<DonatePayDetail> donatePayedDetails = donatePayDetailDao.getItemByTrxidByStatus(trxid,"1");
                        if(donatePayedDetails.isEmpty()) {
                            DonatePayDetail donatePayDetail = donatePayDetails.get(0);
                            donatePayDetail.setPayStatus("1");
                            donatePayDetail.setTrxdate(DateUtil.format(DateUtil.date(),"yyyy-MM-dd"));
                            donatePayDetail.setFintime(notifyData.get("paytime"));
                            int result = donatePayDetailDao.insert(donatePayDetail);
                            log.info("支付回调写入donatePayDetail:{}",result);
                            ProjectDonationDetail projectDonationDetail = new ProjectDonationDetail();
                            projectDonationDetail.setProjectId(donatePayDetail.getProjectId());
                            projectDonationDetail.setProjectName(donatePayDetail.getProjectName());
                            projectDonationDetail.setDonationAmount(donatePayDetail.getTrxamt());
                            projectDonationDetail.setDonationTime(DateUtil.date());
                            projectDonationDetail.setUserId(donatePayDetail.getOpenid());
                            projectDonationDetail.setReqsn(donatePayDetail.getReqsn());
                            projectDonationDetail.setCreateTime(DateUtil.date());
                            projectDonationDetail.setCreateBy(donatePayDetail.getOpenid());
                            UmsMember umsMember = umsMemberService.getByUsername(donatePayDetail.getOpenid());
                            if (null != umsMember) {
                                if(StrUtil.isNotEmpty(umsMember.getCname())) {
                                    projectDonationDetail.setUserName(umsMember.getCname());
                                } else {
                                    projectDonationDetail.setUserName(umsMember.getNickName());
                                }

                            }
                            result = projectDonationDetailMapper.insert(projectDonationDetail);
                            log.info("支付回调写入projectDonationDetail:{}",result);
                            if(result > 0) {
                                umsMemberCacheService.lPushLimit(projectDonationDetail);
                                umsMemberCacheService.setPersonDonationList(projectDonationDetail);
                                return "success";
                            }
                        } else {
                            return "success";
                        }
                    }
                }
            }
        }
        return "fail";
    }

    @Override
    public List<JSONObject> certifiSummary(String openId) {
        UmsMember umsMember = umsMemberService.getByUsername(openId);
        String cname = umsMember.getCname();
        List<JSONObject> result = new ArrayList<>();
        List<DonatePayDetail> donatePayDetails = donatePayDetailDao.getSumTrxamtByOpenId(openId);
        for (DonatePayDetail donatePayDetail:donatePayDetails) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.set("projectName",donatePayDetail.getProjectName());
            jsonObject.set("projectId",donatePayDetail.getProjectId());
            JSONObject projectBasic = projectService.getProjectBasic(donatePayDetail.getProjectId());
            if(null != projectBasic && projectBasic.containsKey("projectDesc")) {
                jsonObject.set("projectDesc",projectBasic.getStr("projectDesc"));
            } else {
                jsonObject.set("projectDesc","");
            }
            if(null != projectBasic && projectBasic.containsKey("projectCertificate")) {
                jsonObject.set("projectCertificate",projectBasic.getStr("projectCertificate"));
            } else {
                jsonObject.set("projectCertificate","");
            }
            if(null != projectBasic && projectBasic.containsKey("projectLogo")) {
                jsonObject.set("projectLogo",projectBasic.getStr("projectLogo"));
            }
            jsonObject.set("totalAmt",donatePayDetail.getTrxamt());
            jsonObject.set("certifiDate",donatePayDetail.getTrxdate());
            jsonObject.set("cname",cname);
            jsonObject.set("openId",openId);
            String projectThanks = donatePayDetailDao.getProjectThanks(donatePayDetail.getProjectId());
            if(StrUtil.isNotEmpty(projectThanks)) {
                jsonObject.set("projectThanks",projectThanks);
            } else {
                jsonObject.set("projectThanks","");
            }
            result.add(jsonObject);
        }
        return result;
    }

    @Override
    public JSONObject getCertificate(String openId,String projectId) {
      DonatePayDetail payDetail = donatePayDetailDao.getCertificate(openId, projectId);
      JSONObject jsonObject = JSONUtil.parseObj(payDetail);
        return jsonObject;
    }

    @Override
    public String getPersonTotalProject(String openId) {
        return donatePayDetailDao.getPersonTotalProject(openId);
    }

    @Override
    public String getPersonTotalDonateAmout(String openId) {
        return donatePayDetailDao.getPersonTotalDonateAmout(openId);
    }

  @Override
  public List<ProjectDonationTotalDto> getDonateTotalByProjectIds(Set<String> ids) {
    if (ids == null || ids.size() <= 0) {
      return emptyList();
    }
    List<ProjectDonationTotalDto> dtos = projectDonationDetailDao.getDonateTotalByProjectIds(ids);
    dtos.parallelStream().forEach(d -> {
      if (ObjectUtil.isEmpty(d.getProjectActualFunding())) {
        d.setProjectActualFunding(new BigDecimal("0.00"));
      }
      if (ObjectUtil.isEmpty(d.getDonationCount())) {
        d.setDonationCount(0);
      }
    });
    return dtos;
  }

  @Override
  public ProjectDonationTotalDto getDonateTotal() {
    List<ProjectDonationTotalDto> total = projectDonationDetailDao.getDonateTotal();
    if (ObjectUtil.isEmpty(total)) {
      ProjectDonationTotalDto zeroDto = new ProjectDonationTotalDto();
      zeroDto.setDonationCount(0);
      zeroDto.setProjectActualFunding(new BigDecimal("0.00"));
      return zeroDto;
    }
    ProjectDonationTotalDto totalDto = total.get(0);
    if (ObjectUtil.isEmpty(totalDto.getProjectActualFunding())) {
      totalDto.setProjectActualFunding(new BigDecimal("0.00"));
    }
    if (ObjectUtil.isEmpty(totalDto.getDonationCount())) {
      totalDto.setDonationCount(0);
    }
    return totalDto;
  }

    @Override
    public List<DonationListDto> getDonateListCurrentMonth(String month) {
        return projectDonationDetailDao.getDonateListCurrentMonth(month);
    }

    @Override
    public List<DonationListDto> getDonateListCurrentYear(String year) {
        return projectDonationDetailDao.getDonateListCurrentYear(year);
    }

    @Override
    public List<DonationListDto> getDonateListTotal() {
        return projectDonationDetailDao.getDonateListTotal();
    }

    @Override
    public String getprojectThanks(String projectId) {
        return donatePayDetailDao.getProjectThanks(projectId);
    }

}
